package com.lds.config.center.server.business.itemchange.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseBatchCreateRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseBatchDeleteRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseBatchUpdateRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseCreateRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseDeleteRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseGetByIdRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseGetByIdsRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseGetByKeyRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseListPageRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseListRequest;
import com.lds.config.center.common.model.itemchange.request.ItemChangeBaseUpdateRequest;
import com.lds.config.center.common.model.itemchange.response.ItemChangeBaseBatchCreateResponse;
import com.lds.config.center.common.model.itemchange.response.ItemChangeBaseBatchDeleteResponse;
import com.lds.config.center.common.model.itemchange.response.ItemChangeBaseBatchUpdateResponse;
import com.lds.config.center.common.model.itemchange.response.ItemChangeBaseDeleteResponse;
import com.lds.config.center.common.model.itemchange.response.ItemChangeBaseListResponse;
import com.lds.config.center.common.model.itemchange.response.ItemChangeBaseResponse;
import com.lds.config.center.server.business.item.entity.Item;
import com.lds.config.center.server.business.item.mapper.ItemMapper;
import com.lds.config.center.server.business.itemchange.converter.ItemChangeBaseCreateRequestToEntityConverter;
import com.lds.config.center.server.business.itemchange.converter.ItemChangeBaseGetByKeyRequestToEntityConverter;
import com.lds.config.center.server.business.itemchange.converter.ItemChangeBaseListPageRequestToEntityConverter;
import com.lds.config.center.server.business.itemchange.converter.ItemChangeBaseListRequestToEntityConverter;
import com.lds.config.center.server.business.itemchange.converter.ItemChangeBaseUpdateRequestToEntityConverter;
import com.lds.config.center.server.business.itemchange.converter.ItemChangeToBaseResponseConverter;
import com.lds.config.center.server.business.itemchange.entity.ItemChange;
import com.lds.config.center.server.business.itemchange.mapper.ItemChangeMapper;
import com.lds.config.center.server.business.itemchange.service.ItemChangeBaseService;
import com.lds.config.center.server.common.enums.ServerErrorEnum;
import com.lds.management.center.common.constant.CommonConstant;
import com.lds.management.center.common.model.db.OrderBy;
import com.lds.management.center.common.model.db.PageResult;
import com.lds.management.center.common.model.dto.ResultDTO;
import com.lds.management.center.common.util.AssertUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 基础服务实现类
 *
 * @author lidongsheng
 * @since 2025-06-30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ItemChangeBaseServiceImpl extends ServiceImpl<ItemChangeMapper, ItemChange> implements ItemChangeBaseService {

    private final ItemChangeMapper itemChangeMapper;
    private final ItemMapper itemMapper;
    private final ItemChangeBaseCreateRequestToEntityConverter itemChangeBaseCreateRequestToEntityConverter;
    private final ItemChangeBaseUpdateRequestToEntityConverter itemChangeBaseUpdateRequestToEntityConverter;
    private final ItemChangeBaseListRequestToEntityConverter itemChangeBaseListRequestToEntityConverter;
    private final ItemChangeToBaseResponseConverter itemChangeToBaseResponseConverter;
    private final ItemChangeBaseListPageRequestToEntityConverter itemChangeBaseListPageRequestToEntityConverter;
    private final ItemChangeBaseGetByKeyRequestToEntityConverter itemChangeBaseGetByKeyRequestToEntityConverter;

    @Override
    @Transactional
    public ResultDTO<ItemChangeBaseResponse> createItemChange(ItemChangeBaseCreateRequest request) {
        boolean existsItem = itemMapper.exists(new QueryWrapper<>(Item.builder().namespaceId(request.getNamespaceId()).name(request.getName()).build()));
        AssertUtil.assertTrue(!existsItem, ServerErrorEnum.ITEM_EXIST);

        try {
            ItemChange itemChange = itemChangeBaseCreateRequestToEntityConverter.convert(request);
            itemChangeMapper.insert(itemChange);
            ItemChangeBaseResponse response = itemChangeToBaseResponseConverter.convert(itemChange);
            return ResultDTO.success(response);
        } catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Transactional
    @Override
    public ResultDTO<ItemChangeBaseBatchCreateResponse> batchCreateItemChange(ItemChangeBaseBatchCreateRequest request) {
        ItemChangeBaseBatchCreateResponse response = ItemChangeBaseBatchCreateResponse.builder()
                .responses(request.getRequests().stream().map(this::createItemChange).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<ItemChangeBaseDeleteResponse> deleteItemChange(ItemChangeBaseDeleteRequest request) {
        itemChangeMapper.deleteById(request.getId());

        ItemChangeBaseDeleteResponse response = ItemChangeBaseDeleteResponse.builder()
                .request(request)
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<ItemChangeBaseBatchDeleteResponse> batchDeleteItemChange(ItemChangeBaseBatchDeleteRequest request) {
        ItemChangeBaseBatchDeleteResponse response = ItemChangeBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().stream().map(this::deleteItemChange).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<ItemChangeBaseResponse> updateItemChange(ItemChangeBaseUpdateRequest request) {
        try {
            ItemChange itemChange = itemChangeBaseUpdateRequestToEntityConverter.convert(request);

            ItemChange currItemChange = itemChangeMapper.selectById(request.getId());
            if (Objects.nonNull(currItemChange)) {
                itemChangeMapper.updateById(itemChange);
            } else {
                itemChange.setCreator(CommonConstant.DEFAULT_USER);
                itemChange.setCreateTime(itemChange.getUpdateTime());
                itemChangeMapper.insert(itemChange);
            }

            ItemChangeBaseResponse response = itemChangeToBaseResponseConverter.convert(itemChange);
            return ResultDTO.success(response);
        } catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Transactional
    @Override
    public ResultDTO<ItemChangeBaseBatchUpdateResponse> batchUpdateItemChange(ItemChangeBaseBatchUpdateRequest request) {
        ItemChangeBaseBatchUpdateResponse response = ItemChangeBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().stream().map(this::updateItemChange).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ItemChangeBaseResponse> getItemChangeById(ItemChangeBaseGetByIdRequest request) {
        ItemChange itemChange = itemChangeMapper.selectById(request.getId());
        if (itemChange == null) {
            return ResultDTO.success();
        }

        ItemChangeBaseResponse response = itemChangeToBaseResponseConverter.convert(itemChange);
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ItemChangeBaseListResponse> getItemChangeByIds(ItemChangeBaseGetByIdsRequest request) {
        List<ItemChange> list = request.getIds().stream().map(id -> itemChangeMapper.selectById(id)).collect(Collectors.toList());
        return ResultDTO.success(ItemChangeBaseListResponse.builder()
                .itemChanges(list.stream().map(itemChange -> itemChangeToBaseResponseConverter.convert(itemChange)).collect(Collectors.toList()))
                .build());
    }

    @Override
    public ItemChange getItemChangeByKey(ItemChangeBaseGetByKeyRequest request) {
        return itemChangeMapper.selectOne(new QueryWrapper<>(itemChangeBaseGetByKeyRequestToEntityConverter.convert(request)));
    }

    @Override
    public ResultDTO<ItemChangeBaseListResponse> listItemChange(ItemChangeBaseListRequest request) {
        QueryWrapper<ItemChange> wrapper = new QueryWrapper<>(itemChangeBaseListRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            wrapper.orderByDesc(request.getOrderByKey());
        }

        List<ItemChange> itemChanges = itemChangeMapper.selectList(wrapper);

        ItemChangeBaseListResponse response = ItemChangeBaseListResponse.builder()
                .itemChanges(itemChanges.stream().map(itemChangeToBaseResponseConverter::convert).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ItemChangeBaseListResponse> listAllItemChange(OrderBy orderBy) {
        ItemChangeBaseListRequest itemChangeRequest = ItemChangeBaseListRequest.builder().build();
        itemChangeRequest.setOrderByKey(orderBy.getOrderByKey());
        return listItemChange(itemChangeRequest);
    }

    @Override
    public ResultDTO<PageResult<ItemChangeBaseResponse>> listItemChangePage(ItemChangeBaseListPageRequest request) {
        Page<ItemChange> page = new Page<>(request.getPageNum(), request.getPageSize(), true);

        QueryWrapper<ItemChange> wrapper = new QueryWrapper<>(itemChangeBaseListPageRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            if (request.getOrderByDesc() != null && request.getOrderByDesc().booleanValue() == false) {
                wrapper.orderByAsc(request.getOrderByKey());
            } else {
                wrapper.orderByDesc(request.getOrderByKey());
            }
        }

        IPage<ItemChange> pageResult = itemChangeMapper.selectPage(page, wrapper);

        PageResult<ItemChangeBaseResponse> response = new PageResult(
                pageResult.getTotal(), pageResult.getPages(), pageResult.getCurrent(), pageResult.getSize(),
                pageResult.getRecords().stream().map(itemChangeToBaseResponseConverter::convert).collect(Collectors.toList()));
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ItemChangeBaseBatchCreateResponse> batchCreateItemChangeAsync(ItemChangeBaseBatchCreateRequest request) {
        ItemChangeBaseBatchCreateResponse response = ItemChangeBaseBatchCreateResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::createItemChange).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ItemChangeBaseBatchDeleteResponse> batchDeleteItemChangeAsync(ItemChangeBaseBatchDeleteRequest request) {
        ItemChangeBaseBatchDeleteResponse response = ItemChangeBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::deleteItemChange).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ItemChangeBaseBatchUpdateResponse> batchUpdateItemChangeAsync(ItemChangeBaseBatchUpdateRequest request) {
        ItemChangeBaseBatchUpdateResponse response = ItemChangeBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().parallelStream().map(this::updateItemChange).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

}
